'''
Created on Aug 2, 2011

@author: elia
'''

import rdflib
from rdflib.store import Store, VALID_STORE
from rdflib import plugin
from rdflib.graph import Graph
from rdflib.term import URIRef, Literal
from rdflib.namespace import Namespace, RDF

class Semantic_manager():
    
    __graph = None
    __graph_URI = 'http://thesis.eliacontini.info'
    __mrEdu = Namespace("http://thesis.eliacontini.info/semantic/")
    __store = None
    
    def __init__(self, db_path):
        print db_path
        # plugin registration
        rdflib.plugin.register('sparql', rdflib.query.Processor, 'rdfextras.sparql.processor', 'Processor')
        rdflib.plugin.register('sparql', rdflib.query.Result, 'rdfextras.sparql.query', 'SPARQLQueryResult')
        rdflib.plugin.register('SQLite', Store, 'rdfstorage.SQLite', 'SQLite')

        # storage
        self.__store = plugin.get('SQLite', Store)(db_path)
        rt = self.__store.open('.' ,create = False)
        if rt == 0:
            # if schema doesn't exist create it
            self.__store.open('.' ,create = True)
        else:
            assert rt == VALID_STORE, "The underlying store is corrupted"
        
        self.__graph = Graph(self.__store, identifier = URIRef(self.__graph_URI))
        self.__graph.bind("mrEdu", "http://thesis.eliacontini.info/semantic/")
    
    def __del__(self):
        self.__graph.close()
        #self.__store.destroy('.')
    
    def addGroupMember(self, groupData, userData):
        if groupData is None or userData is None:
            raise ValueError('Specify group and user information')
        else:
            group = URIRef(groupData.get('uri'))
            user = URIRef(userData.get('uri'))
            self.__graph.add( (group, self.__mrEdu['member'], user) )
            self.__graph.commit()
    
    def insertAudio(self, audioData = None, userData = None):
        if audioData is None or userData is None:
            raise ValueError('Specify audio and user information')
        else:
            audio = URIRef(audioData.get('uri'))
            user = URIRef(userData.get('uri'))
            self.__graph.add( (audio, RDF.type, self.__mrEdu['Audio']) )
            self.__graph.add( (audio, self.__mrEdu['ID'], Literal(audioData.get('ID'))) )
            self.__graph.add( (audio, self.__mrEdu['page'], Literal(audioData.get('uri'))) )
            self.__graph.add( (audio, self.__mrEdu['name'], Literal(audioData.get('name'))) )
            self.__graph.add( (audio, self.__mrEdu['description'], Literal(audioData.get('description'))) )
            self.__graph.add( (audio, self.__mrEdu['maker'], user) )
            self.__graph.add( (audio, self.__mrEdu['isAbout'], Literal(audioData.get('about'))) )
            self.__graph.add( (audio, self.__mrEdu['creationDate'], Literal(audioData.get('creationDate'))) )
            self.__graph.add( (audio, self.__mrEdu['resource'], Literal(audioData.get('resource'))) )
            self.__graph.add( (audio, self.__mrEdu['contentType'], Literal(audioData.get('contentType'))) )
            self.__graph.commit()
    
    def insertGroup(self, groupData = None):
        if groupData is None:
            raise ValueError('Specify group information')
        else:
            group = URIRef(groupData.get('uri'))
            self.__graph.add( (group, RDF.type, self.__mrEdu['Group']) )
            self.__graph.add( (group, self.__mrEdu['name'], Literal(groupData.get('name'))) )
            self.__graph.commit()
      
    def insertImage(self, imageData = None, userData = None):
        if imageData is None or userData is None:
            raise ValueError('Specify image and user information')
        else:
            image = URIRef(imageData.get('uri'))
            user = URIRef(userData.get('uri'))
            self.__graph.add( (image, RDF.type, self.__mrEdu['Image']) )
            self.__graph.add( (image, self.__mrEdu['ID'], Literal(imageData.get('ID'))) )
            self.__graph.add( (image, self.__mrEdu['page'], Literal(imageData.get('uri'))) )
            self.__graph.add( (image, self.__mrEdu['name'], Literal(imageData.get('name'))) )
            self.__graph.add( (image, self.__mrEdu['description'], Literal(imageData.get('description'))) )
            self.__graph.add( (image, self.__mrEdu['maker'], user) )
            self.__graph.add( (image, self.__mrEdu['isAbout'], Literal(imageData.get('about'))) )
            self.__graph.add( (image, self.__mrEdu['creationDate'], Literal(imageData.get('creationDate'))) )
            self.__graph.add( (image, self.__mrEdu['resource'], Literal(imageData.get('resource'))) )
            self.__graph.add( (image, self.__mrEdu['contentType'], Literal(imageData.get('contentType'))) )
            self.__graph.commit()
    
    def insertText(self, textData = None, userData = None):
        if textData is None or userData is None:
            raise ValueError('Specify text and user information')
        else:
            text = URIRef(textData.get('uri'))
            user = URIRef(userData.get('uri'))
            self.__graph.add( (text, RDF.type, self.__mrEdu['Text']) )
            self.__graph.add( (text, self.__mrEdu['ID'], Literal(textData.get('ID'))) )
            self.__graph.add( (text, self.__mrEdu['page'], Literal(textData.get('uri'))) )
            self.__graph.add( (text, self.__mrEdu['name'], Literal(textData.get('name'))) )
            self.__graph.add( (text, self.__mrEdu['description'], Literal(textData.get('description'))) )
            self.__graph.add( (text, self.__mrEdu['maker'], user) )
            self.__graph.add( (text, self.__mrEdu['isAbout'], Literal(textData.get('about'))) )
            self.__graph.add( (text, self.__mrEdu['creationDate'], Literal(textData.get('creationDate'))) )
            self.__graph.add( (text, self.__mrEdu['resource'], Literal(textData.get('resource'))) )
            self.__graph.add( (text, self.__mrEdu['contentType'], Literal(textData.get('contentType'))) )
            self.__graph.commit()
    
    def insertUser(self, userData):
        if userData is None:
            raise ValueError('Specify user information')
        else:
            user = URIRef(userData.get('uri'))
            self.__graph.add( (user, RDF.type, self.__mrEdu['Person']) )
            self.__graph.add( (user, self.__mrEdu['firstName'], Literal(userData.get('name'))) )
            self.__graph.add( (user, self.__mrEdu['surname'], Literal(userData.get('surname'))) )
            self.__graph.commit()
    
    def insertVideo(self, videoData = None, userData = None):
        if videoData is None or userData is None:
            raise ValueError('Specify video and user information')
        else:
            video = URIRef(videoData.get('uri'))
            user = URIRef(userData.get('uri'))
            self.__graph.add( (video, RDF.type, self.__mrEdu['Video']) )
            self.__graph.add( (video, self.__mrEdu['ID'], Literal(videoData.get('ID'))) )
            self.__graph.add( (video, self.__mrEdu['page'], Literal(videoData.get('uri'))) )
            self.__graph.add( (video, self.__mrEdu['name'], Literal(videoData.get('name'))) )
            self.__graph.add( (video, self.__mrEdu['description'], Literal(videoData.get('description'))) )
            self.__graph.add( (video, self.__mrEdu['maker'], user) )
            self.__graph.add( (video, self.__mrEdu['isAbout'], Literal(videoData.get('about'))) )
            self.__graph.add( (video, self.__mrEdu['creationDate'], Literal(videoData.get('creationDate'))) )
            self.__graph.add( (video, self.__mrEdu['resource'], Literal(videoData.get('resource'))) )
            self.__graph.add( (video, self.__mrEdu['contentType'], Literal(videoData.get('contentType'))) )
            self.__graph.commit()
    
    def getContents(self, keywords, criteria):
        audioQuery = '''
            ?audio a mrEdu:Audio .   
            ?audio mrEdu:ID ?ID .
            ?audio mrEdu:name ?name .
            ?audio mrEdu:description ?description .
            ?audio mrEdu:page ?page .
            ?audio mrEdu:resource ?resource .
            ?audio mrEdu:contentType ?contentType .
            ?audio mrEdu:creationDate ?creationDate .
            ?audio mrEdu:isAbout ?subject .
        ''' + 'FILTER REGEX(?subject, "' + keywords + '")'
        
        imageQuery = '''
            ?image a mrEdu:Image .   
            ?image mrEdu:ID ?ID .
            ?image mrEdu:name ?name .
            ?image mrEdu:description ?description .
            ?image mrEdu:page ?page .
            ?image mrEdu:resource ?resource .
            ?image mrEdu:contentType ?contentType .
            ?image mrEdu:creationDate ?creationDate .
            ?image mrEdu:isAbout ?subject .
        ''' + 'FILTER REGEX(?subject, "' + keywords + '")'
        
        textQuery = '''
            ?text a mrEdu:Text .   
            ?text mrEdu:ID ?ID .
            ?text mrEdu:name ?name .
            ?text mrEdu:description ?description .
            ?text mrEdu:page ?page .
            ?text mrEdu:resource ?resource .
            ?text mrEdu:contentType ?contentType .
            ?text mrEdu:creationDate ?creationDate .
            ?text mrEdu:isAbout ?subject .
        ''' + 'FILTER REGEX(?subject, "' + keywords + '")'
        
        videoQuery = '''
            ?video a mrEdu:Video .   
            ?video mrEdu:ID ?ID .
            ?video mrEdu:name ?name .
            ?video mrEdu:description ?description .
            ?video mrEdu:page ?page .
            ?video mrEdu:resource ?resource .
            ?video mrEdu:contentType ?contentType .
            ?video mrEdu:creationDate ?creationDate .
            ?video mrEdu:isAbout ?subject .
        ''' + 'FILTER REGEX(?subject, "' + keywords + '")'
        
        query = '''
            PREFIX mrEdu: <http://thesis.eliacontini.info/semantic/>
            SELECT ?ID ?name ?description ?page ?resource ?contentType ?creationDate 
            WHERE
                {
        '''
        defaultWhere = query + '{' + audioQuery + '} UNION {' + imageQuery + '} UNION {' + textQuery + '} UNION {' + videoQuery + '}'
        if len(criteria) > 0:
            for key, value in criteria.items():
                if key == 'type':
                    try:
                        value.index('all')
                        query = defaultWhere
                    except:
                        for i in range(0, len(value)):
                            if len(value) > 1:
                                query = query + '{'
                            
                            if value[i] == 'audio':
                                query = query + audioQuery
                            if value[i] == 'image':
                                query = query + imageQuery
                            if value[i] == 'text':
                                query = query + textQuery
                            if value[i] == 'video':
                                query = query + videoQuery
                            
                            if len(value) > 1:
                                query = query + '}'
                            
                            if i < (len(value) - 1):
                                query = query + ' UNION '
                elif key == 'folder':
                    query = defaultWhere
        else:
            query = defaultWhere
        
        query = query + '}'
        
        #print query
        
        result = list()
        for (ID, name, description, page, resource, contentType, creationDate) in self.__graph.query(query).serialize('python'):
            data = dict()
            data['ID'] = str(ID)
            data['name'] = str(name)
            data['uri'] = str(page)
            data['description'] = str(description)
            data['resource'] = str(resource)
            data['contentType'] = str(contentType)
            data['creationDate'] = str(creationDate)
            
            result.append(data)
        
        return result
    
    def debug(self):
        print self.__graph.serialize()